package org.vacoor.xqq.core.mod.client.impl;

import org.vacoor.xqq.core.mod.authc.AccessToken;
import org.vacoor.xqq.core.mod.authc.AuthenticationToken;
import org.vacoor.xqq.core.mod.authc.exception.AuthenticationException;
import org.vacoor.xqq.core.mod.authc.impl.WebQQAccessToken;
import org.vacoor.xqq.core.mod.authc.impl.WebQQAuthenticator;
import org.vacoor.xqq.core.mod.client.AbstractAppClient;
import org.vacoor.xqq.core.mod.sender.MessageSender;
import org.vacoor.xqq.core.mod.sender.impl.SimpleMessageSender;
import org.vacoor.xqq.core.msg.SendableMessage;
import org.vacoor.xqq.core.msg.impl.SimpleSendableMessage;

import java.util.Date;
import java.util.Random;

/**
 */
public class WebQQClient extends AbstractAppClient {
    private static WebQQClient client;

    private final long clientId;
    private MessageSender sender;

    private WebQQClient() {
        /* 按照 WebQQ 算法生成一个 client id, 100以内随机数 + 时间低六位 */
        clientId = new Random().nextInt(100) * Math.round(1E6) + Math.round(new Date().getTime() % 1E6);
        authenticator = new WebQQAuthenticator();
        sender = new SimpleMessageSender();
    }

    public static WebQQClient getCurrentClient() {
        if (client != null) {
            return client;
        }

        synchronized (WebQQClient.class) {
            if (client == null) {
                client = new WebQQClient();
            }
        }
        return client;
    }

    @Override
    protected AccessToken createAccessToken() {
        WebQQAccessToken accessToken = new WebQQAccessToken();
        accessToken.setClientId(clientId);
        return accessToken;
    }

    @Override
    public void login(AuthenticationToken token) throws AuthenticationException {
        ensureAuthenticatorSet();
        this.accessToken = authenticator.login(token);
        this.pricipal = token.getPrincipal();
        this.credentials = token.getCredentials();
    }

    public void relink() throws AuthenticationException {
        WebQQAccessToken accessToken = getWebQQAccessToken();
        if (!accessToken.isAuthenticated()) {
            throw new AuthenticationException("can not relink to server: not found authenticated accessToken");
        }
        ((WebQQAuthenticator) authenticator).linkToServer(accessToken);
    }

    @Override
    public void logout() {
        if (accessToken.isAuthenticated()) {
            ensureAuthenticatorSet();
            authenticator.logout();
            accessToken.setAuthenticated(false);
        }
    }

    protected void ensureAuthenticatorSet() {
        if (authenticator == null) {
            throw new IllegalStateException("authenticator must be set");
        }
    }

    public SendableMessage createSendableMessage() {
        return new SimpleSendableMessage() {
            @Override
            protected void doSend() {
                if (sender == null) {
                    throw new IllegalArgumentException("must be set sender");
                }
                sender.send(this, getWebQQAccessToken());
            }
        };
    }
}
